/*
 *  Copyright 2001-2004 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package ar.uba.fi.posgrado.economy.web.action.debt;

import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;

import ar.uba.fi.posgrado.academy.model.Course;
import ar.uba.fi.posgrado.academy.service.CourseService;
import ar.uba.fi.posgrado.common.exception.MissingArgumentException;
import ar.uba.fi.posgrado.common.model.Student;
import ar.uba.fi.posgrado.economy.service.CustomerService;
import ar.uba.fi.posgrado.common.service.StudentService;
import ar.uba.fi.posgrado.common.util.CommonUtils;
import ar.uba.fi.posgrado.economy.exception.DebtRuleException;
import ar.uba.fi.posgrado.economy.model.Benefit;
import ar.uba.fi.posgrado.economy.model.Customer;
import ar.uba.fi.posgrado.economy.model.Debt;
import ar.uba.fi.posgrado.economy.model.DebtType;
import ar.uba.fi.posgrado.economy.model.Discount;
import ar.uba.fi.posgrado.economy.service.BenefitService;
import ar.uba.fi.posgrado.economy.service.DebtService;
import ar.uba.fi.posgrado.economy.service.DiscountService;
import ar.uba.fi.posgrado.economy.web.form.debt.DebtForm;

/**
 * Modifica la deuda.<br>
 * 
 * @author nicolas.gonzalez
 * @see Action
 */
public class ModifyDebtAction extends Action {

	/** Logger */
	private static Logger logger = Logger.getLogger(ModifyDebtAction.class);
	
    private DebtService debtService;
    private CourseService courseService;
    private CustomerService customerService;
    private StudentService studentService;
    private BenefitService benefitService;
    private DiscountService discountService;
    
    // IoC
    public void setDebtService(DebtService debtService) {
        this.debtService = debtService;
    }
    public void setCourseService(CourseService courseService) {
        this.courseService = courseService;
    }
    public void setCustomerService(CustomerService customerService) {
        this.customerService = customerService;
    }
    public void setStudentService(StudentService studentService) {
        this.studentService = studentService;
    }
    public void setBenefitService(BenefitService benefitService) {
        this.benefitService = benefitService;
    }
    public void setDiscountService(DiscountService discountService) {
        this.discountService = discountService;
    }

    /**
     * @see org.apache.struts.action.Action#execute(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
     */
    @SuppressWarnings("unchecked")
    @Override
    public ActionForward execute(ActionMapping mapping, ActionForm actionForm,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        if (logger.isDebugEnabled()) {
            logger.debug("Por crear una(s) deuda(s) ...");
        }
        DebtForm form = (DebtForm)actionForm;
        Student student = this.studentService.getById(form.getStudentId());
        Customer customer = this.customerService.getById(form.getCustomerId());
        Course course = this.courseService.getById(new Long(form.getCourseSelected()));
        
        if (!student.getCourses().contains(course)) {
            logger.warn("Intentando crear una deuda para un alumno asociandolo a un curso en donde no esta inscripto...");
            
            ActionMessages errors = new ActionMessages();
            errors.add("debt.rule", new ActionMessage("debt.studentAndCourse"));
            saveErrors(request, errors);
            return mapping.getInputForward();
        }
        
        Date validityFrom = CommonUtils.toDateFromStringStandard(form.getValidityFrom());
        Date expiry = CommonUtils.toDateFromStringStandard(form.getExpiry());
        
        Double balance = form.getBalance();
        Double originalBalance = balance;
        String reason = form.getReason();
        
        DebtType debtType = this.debtService.getDebtTypeById(new Long(form.getDebtTypeSelected()));
        List<Long> benefitIds = form.getSelectedBenefitsIds();
        List<Long> discountIds = form.getSelectedDiscountsIds();
        List<Benefit> benefits = this.benefitService.getBenegitsByIds(benefitIds);
        List<Discount> discounts = this.discountService.getDiscountsByIds(discountIds); 
        
        if (logger.isDebugEnabled()) {
            logger.debug(   "Informacion de la deuda nueva obtenida. Invocando al servicio de modificacion " +  
                            " de deuda ...");
        }
        Long debtId = form.getId();
        Debt debt = this.debtService.getById(debtId);
        
        Date newValidityFrom = validityFrom;
        Date newExpiry = expiry;
        debt.setValidityFrom(newValidityFrom);
        debt.setExpiry(newExpiry);

        debt.setStudent(student);
        debt.setCustomer(customer);
        debt.setCourse(course);
        debt.setBody(course.getBody());
        debt.setBalance(balance);
        debt.setOriginalBalance(originalBalance);
        debt.setDebtType(debtType);
        debt.setReason(reason);
        debt.setBenefits(CommonUtils.listToSet(benefits));
        debt.setDiscounts(CommonUtils.listToSet(discounts));

        try {
            this.debtService.update(debt);
        }
        catch (MissingArgumentException e) {
            logger.warn("Intentando modificar una deuda sin los campos obligatorios...");
            
            ActionMessages errors = new ActionMessages();
            errors.add("debt.missingArguments", new ActionMessage(e.getMessage(), false));
            saveErrors(request, errors);

            return mapping.getInputForward();
        }
        catch (DebtRuleException e) {
            logger.warn("Intentando modificar una deuda sin haber cumplido las reglas...");
            
            ActionMessages errors = new ActionMessages();
            errors.add("debt.rule", new ActionMessage(e.getMessage(), false));
            saveErrors(request, errors);

            return mapping.getInputForward();
        }
        
        logger.info("Deuda modificada con exito");
        return mapping.findForward("success");
    }

	
}
